import _ from 'lodash'
const { isString, isBoolean, isUndefined, merge, isPlainObject, isArray } = _
import { ECHARTS } from '../constants/base'
import { LINE_BAR_DEFAULT } from '../constants/lineBarDefault'

/*
options中所有选项均 非必传 项, 如没传获取默认配置, 传Boolean值也获取默认配置
options: {
  title: String | Object, 可传字符串或echarts title对象
  label: Boolean | Object, 可传Boolean或echarts series.label对象
  legend: Boolean | Object, 可传Boolean或echarts legend对象
  smooth: Boolean, 可传Boolean
  stack: Boolean, 可传Boolean或自定义字符串
  area: Boolean, 可传Boolean或echarts series.areaStyle对象
  yAxis: Object | Array, 可传echarts yAxis对象/数组, 如不传根据seriesData分析获取
  tooltip: Boolean | Object, 可传Boolean或echarts tooltip对象
  dataZoom: Boolean | Array | Object 可传Boolean或echarts dataZoom对象/数组
  transverseXY: Boolean 可传Boolean, 翻转XY轴
}

series数组中每一项代表一组数据, 该数据中 name, data 必传
series: [
  {
    name: String, 该组数据名称
    data: Array, 数据list
    type: 'line' | 'bar', 该组数据展示类型, 默认line
    yAxisIndex: 0 | 1, 该组数据对应的y轴, 默认0
    label: Boolean, 可传Boolean, 覆盖options.label配置
    markPoint: Object, 可传echarts series.markPoint对象
    markLine: Object 可传echarts series.markLine对象
  }
]
*/
export default class OptionsFormat {
  constructor(ctx) {
    const { fromData, fromOptions, type } = ctx
    this.fromData = fromData
    this.fromOptions = fromOptions
    this.type = type
    this.options = {}
    this.format()
  }

  format() {
    if (this.type === ECHARTS) {
      this.options = this.fromData
    } else {
      const { categories, series: seriesData } = this.fromData
      const { default_title, default_label, default_legend, default_stack, default_area, default_yAxis, default_tooltip, default_dataZoom } = LINE_BAR_DEFAULT
      const { title, label, legend, smooth, stack, area, yAxis, tooltip, dataZoom, transverseXY } = this.fromOptions

      const $$title = this.formatTitle(default_title, title)
      let $$xAxis = this.formatXAxis(categories)
      let $$yAxis = this.formatYAxis(default_yAxis, yAxis, seriesData)
      if (transverseXY) {
        [$$xAxis, $$yAxis] = [$$yAxis, $$xAxis]
      }
      const $$series = this.formatSeries(seriesData, default_stack, stack, default_area, area, default_label, label, smooth, transverseXY)
      const $$legend = this.formatLegend(default_legend, legend)
      const $$tooltip = this.formatTooltip(default_tooltip, tooltip)

      this.options = {
        title: $$title,
        legend: $$legend,
        xAxis: $$xAxis,
        yAxis: $$yAxis,
        series: $$series,
        tooltip: $$tooltip
      }

      this.formatDataZoom(default_dataZoom, dataZoom, this.options)
    }
  }

  formatTitle(dTitle, title) {
    let _title = dTitle
    if (!isUndefined(title)) {
      if (isString(title)) { // 传字符串
        _title.text = title
      } else if (isPlainObject(title)) { // 传对象
        _title = merge(dTitle, title)
      }
    }
    return _title
  }

  formatXAxis(categories) {
    const _xAxis = {
      type: 'category',
      data: categories
    }
    return _xAxis
  }

  formatYAxis(dYAxis, yAxis, seriesData) {
    let _yAxis = dYAxis
    if (isPlainObject(yAxis)) { // 可传对象
      _yAxis = merge(dYAxis, yAxis)
    } else if (isArray(yAxis)) { // 可传数组
      _yAxis = yAxis.map(item => {
        if (isString(item)) { // 数组中只有name
          return { ...dYAxis, name: item }
        } else {
          return item
        }
      })
    } else if (isUndefined(yAxis)) {
      const serieYAxisIndex = seriesData.filter(item => !isUndefined(item.yAxisIndex))
      if (serieYAxisIndex.length) {
        _yAxis = serieYAxisIndex.map(item => ({ ...dYAxis, yAxisIndex: item.yAxisIndex }))
      } else {
        _yAxis = dYAxis
      }
    }
    return _yAxis
  }

  formatSeries(seriesData, dStack, stack, dArea, area, dLabel, label, smooth, transverseXY) {
    const stackValue = dStack()
    const _series = seriesData.map(({ name, data, type, yAxisIndex, label: singleLabel, stack: singleStack, markPoint, markLine }) => {
      const _label = this.formatLabel(dLabel, singleLabel, label, transverseXY)
      const serie = {
        type: type || 'line',
        data,
        name,
        label: _label,
        smooth,
        markPoint,
        markLine
      }
      !isUndefined(yAxisIndex) && (serie.yAxisIndex = yAxisIndex)
      this.formatStack(serie, stackValue, singleStack, stack)
      this.formatArea(serie, dArea, area)
      return serie
    })
    return _series
  }

  formatLabel(dLabel, singleLabel, label, transverseXY) {
    transverseXY && (dLabel.position = 'insideRight')
    let _label = {}
    if (!isUndefined(singleLabel)) {
      if (isBoolean(singleLabel)) {
        if (singleLabel) {
          _label = dLabel
        }
      } else {
        _label = merge(dLabel, singleLabel)
      }
    } else {
      if (!isUndefined(label)) {
        if (isBoolean(label)) {
          if (label) {
            _label = dLabel
          }
        } else {
          _label = merge(dLabel, label)
        }
      }
    }
    return _label
  }

  formatStack(serie, stackValue, singleStack, stack) {
    if (!isUndefined(singleStack)) {
      if (isBoolean(singleStack)) {
        if (singleStack) {
          serie.stack = stackValue
        }
      } else if (isString(singleStack)) {
        serie.stack = singleStack
      }
    } else {
      if (isBoolean(stack)) {
        if (stack) {
          serie.stack = stackValue
        }
      } else if (isString(stack)) {
        serie.stack = stack
      }
    }
  }

  formatArea(serie, dArea, area) {
    if (!isUndefined(area)) {
      if (isBoolean(area)) {
        serie.areaStyle = dArea
      }
    } else if (isPlainObject(area)) {
      serie.areaStyle = merge(dArea, area)
    }
  }

  formatLegend(dLegend, legend) {
    let _legend = {}
    if (!isUndefined(legend)) {
      if (isBoolean(legend)) {
        if (legend) {
          _legend = dLegend
        }
      } else {
        _legend = merge(dLegend, legend)
      }
    } else {
      _legend = dLegend
    }
    return _legend
  }

  formatTooltip(dTooltip, tooltip) {
    let _tooltip = {}
    if (!isUndefined(tooltip)) {
      if (isBoolean(tooltip)) {
        if (tooltip) {
          _tooltip = dTooltip
        }
      } else {
        _tooltip = merge(dTooltip, tooltip)
      }
    } else {
      _tooltip = dTooltip
    }
    return _tooltip
  }

  formatDataZoom(dDataZoom, dataZoom, options) {
    if (!isUndefined(dataZoom)) {
      if (isBoolean(dataZoom)) {
        if (dataZoom) {
          options.dataZoom = dDataZoom()
        }
      } else if (isPlainObject(dataZoom) || isArray(dataZoom)) {
        options.dataZoom = dataZoom
      }
    }
  }
}
